💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    정규화 | ✅저자: 이유정(박사)

    🔹 정규화란? 데이터를 중복 없이 정리하고, 나중에 에러 없이 쉽게 관리할 수 있게 테이블 구조를 만드는 규칙입니다.

    ❓ 왜 필요할까요?

    • 데이터를 중복으로 쓰면 저장 공간 낭비.
    • 하나만 바꾸면 되는 정보를 여러 군데 바꿔야 해서 오류 발생 가능성 높음.
    • 테이블이 너무 복잡하거나 너무 커지는 걸 방지.

    🔹 혼합된 비정규형 테이블
    학생ID 학생이름 반이름 반선생님 연락처 과목명 점수
    1 철수 1반 김선생님 010-1111-1111, 010-2222-2222 수학 90
    1 철수 1반 김선생님 010-1111-1111, 010-2222-2222 영어 85
    2 영희 1반 김선생님 010-3333-3333 수학 95
    3 민수 2반 박선생님 010-4444-4444 영어 88

    ◽ 제1정규형 (1NF) – 원자값(더 이상 나눌 수 없는 값)만 허용

    📖 규칙:

    • 각 칸(컬럼)은 하나의 값만 가져야 합니다.
    • 즉, 한 셀에 두 개 이상의 정보가 있으면 안됩니다.
    학생ID 학생이름 반이름 반선생님 연락처 과목명 점수
    1 철수 1반 김선생님 010-1111-1111 수학 90
    1 철수 1반 김선생님 010-2222-2222 수학 90
    1 철수 1반 김선생님 010-1111-1111 영어 85
    1 철수 1반 김선생님 010-2222-2222 영어 85
    2 영희 1반 김선생님 010-3333-3333 수학 95
    3 민수 2반 박선생님 010-4444-4444 영어 88
    ✅ 연락처 한 셀에 하나만 넣었어요 → 원자값만 존재 → 1NF 완료

    ◽ 제2정규형 (2NF) – 부분 종속 제거 (복합키의 일부에만 의존하는 속성 분리)

    📖 규칙:

    • 기본키는 (학생ID + 과목명)
    • 그런데 학생이름, 반이름, 반선생님, 연락처는 과목 없이도 학생ID만 알면 됩니다.
    📄 학생 테이블 (학생 정보만)
    학생ID 학생이름 반이름 연락처
    1 철수 1반 010-1111-1111
    1 철수 1반 010-2222-2222
    2 영희 1반 010-3333-3333
    3 민수 2반 010-4444-4444
    📄 성적 테이블 (학생ID + 과목명 기준)
    학생ID 과목명 점수
    1 수학 90
    1 영어 85
    2 수학 95
    3 영어 88
    ✅ 과목 관련 정보만 남기고 나머지 정보는 학생 테이블로 이동
    → 부분 종속 제거 → 2NF 완료
    • 이 표의 기본키는 (학생ID, 과목)이에요. 왜냐하면 같은 학생이 여러 과목을 들으니까요.
    • 그런데 학생이름과목이랑은 아무 상관이 없잖아요? “학생 이름은 과목에 따라 바뀌는 것도 아닌데 같이 있을 필요가 없습니다. 그래서 학생의 이름은 학생ID랑만 연결합니다.

    💡 핵심 규칙: 복합키일 때, 그 일부에만 의존하는 정보는 따로 떼어내기!


    ◽ 제3정규형 (3NF) – 이행 종속 제거

    📖 규칙:

    • 반이름반선생님 이므로,
    • 반선생님은 중간 컬럼(반이름)을 거쳐야만 알 수 있습니다. 그래서 분리해야 합니다.
    • 반 정보를 따로 빼서 반이름반선생님을 연결!
    📄 반 테이블
    반이름 반선생님
    1반 김선생님
    2반 박선생님
    ✅ 이제 모든 테이블이 역할별로 완전히 정리되었습니다.
    → 3NF까지 완료!

    ✅ 최종 정규화 완료: 4개의 테이블로 나눠짐

    학생ID 학생이름 반이름
    1 철수 1반
    2 영희 1반
    3 민수 2반
    학생 테이블: 학생의 고유 정보 (ID, 이름, 반)
    학생ID 연락처
    1 010-1111-1111
    1 010-2222-2222
    2 010-3333-3333
    3 010-4444-4444
    연락처 테이블: 학생 1명이 여러 연락처를 가질 수 있으므로 분리 (1:N 관계)
    학생ID 과목명 점수
    1 수학 90
    1 영어 85
    2 수학 95
    3 영어 88
    성적 테이블: 복합키 (학생ID, 과목명) 기반으로 성적 저장
    반이름 반선생님
    1반 김선생님
    2반 박선생님
    반 테이블: 반이름을 기준으로 반선생님을 구분

    ✅ 관계 요약 (ERD 개념)

    • 학생ID연락처, 성적, 학생 테이블과 연결됨
    • 반이름학생, 반 테이블과 연결됨

    📖 정규화 정리
    정규화 단계 규칙 설명 쉽게 말하면…
    1NF (제1정규형) 원자값만 허용 셀마다 값 하나만 써야 해요.
    2NF (제2정규형) 부분 종속 제거 복합키의 일부에만 의존하는 컬럼은 빼요.
    3NF (제3정규형) ...... 이행 종속 제거 ..... 기본키를 거치지 않고 다른 컬럼을 통해서만 알 수 있는 정보는 분리해요.

    1. Student: 학생 기본 정보 (student_id, name, classroom)
    2. Phone: 연락처 (1명의 학생이 여러 연락처 가능)
    3. Score: 성적 정보 (student, subject, score)
    4. Classroom: 반 정보 (class_name, teacher)

    Django 모델

    # models.py
    
    from django.db import models
    
    # 1. 반 정보 테이블
    class Classroom(models.Model):
        class_name = models.CharField(max_length=10, unique=True)  # 예: '1반', '2반'
        teacher = models.CharField(max_length=50)  # 예: '김선생님'
    
        def __str__(self):
            return f"{self.class_name} ({self.teacher})"
    
    
    # 2. 학생 테이블
    class Student(models.Model):
        name = models.CharField(max_length=50)
        classroom = models.ForeignKey(Classroom, on_delete=models.CASCADE, related_name='students')
    
        def __str__(self):
            return f"{self.name} - {self.classroom.class_name}"
    
    
    # 3. 연락처 테이블
    class Phone(models.Model):
        student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='phones')
        number = models.CharField(max_length=20)
    
        def __str__(self):
            return f"{self.student.name}: {self.number}"
    
    
    # 4. 성적 테이블
    class Score(models.Model):
        student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='scores')
        subject = models.CharField(max_length=30)
        score = models.PositiveIntegerField()
    
        class Meta:
            unique_together = ('student', 'subject')  # 복합키 대체
    
        def __str__(self):
            return f"{self.student.name} - {self.subject}: {self.score}"
    

    Classroom : 반이름(class_name)과 반선생님(teacher)을 저장 Student : 학생이름(name)과 소속 반(classroom)을 연결 Phone : 학생의 연락처 — 학생당 여러 개 가능 (1:N) Score : 학생과 과목, 점수를 저장 — 학생ID + 과목이 고유 (복합키 역할)

    TOP
    preload preload